package indi.zhifa.recipe.bailan.framework.auth.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import indi.zhifa.recipe.bailan.framework.auth.dao.IBaseAuthNodeRelevantDao;
import indi.zhifa.recipe.bailan.framework.auth.dao.IBaseUserRelevantDao;
import indi.zhifa.recipe.bailan.framework.auth.dao.service.IRelUserDepDbService;
import indi.zhifa.recipe.bailan.framework.auth.dao.service.IUserDbService;
import indi.zhifa.recipe.bailan.framework.auth.dao.service.IUserWithRoleAndAuthDbService;
import indi.zhifa.recipe.bailan.framework.auth.entity.dto.user.EditUserDto;
import indi.zhifa.recipe.bailan.framework.auth.entity.dto.user.SignInDto;
import indi.zhifa.recipe.bailan.framework.auth.entity.enums.Gender;
import indi.zhifa.recipe.bailan.framework.auth.entity.po.RelUserAuthEntity;
import indi.zhifa.recipe.bailan.framework.auth.entity.po.UserEntity;
import indi.zhifa.recipe.bailan.framework.auth.entity.po.UserWithRoleAndAuthViewEntity;
import indi.zhifa.recipe.bailan.framework.auth.entity.vo.UserVo;
import indi.zhifa.recipe.bailan.framework.auth.property.UserConfig;
import indi.zhifa.recipe.bailan.framework.auth.service.IUserService;
import indi.zhifa.recipe.bailan.framework.auth.util.IBaseTokenUtil;
import indi.zhifa.recipe.bailan.framework.common.entity.exception.ServiceException;
import indi.zhifa.recipe.bailan.framework.common.util.DtoEntityUtil;
import indi.zhifa.recipe.bailan.framework.mysql.utils.DbDtoEntityUtil;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDate;
import java.util.List;

@Component
public class UserServiceImpl extends BaseUserServiceImpl implements IUserService {

    private final IUserDbService mUserDbService;
    private final IUserWithRoleAndAuthDbService mUserWithRoleDbService;
    private final IRelUserDepDbService mRelUserDepDbService;

    public UserServiceImpl(IBaseUserRelevantDao pUserRelevantDao,
                           IBaseAuthNodeRelevantDao pDepartmentRelevantDao,
                           UserConfig pUserConfig,
                           PasswordEncoder pPasswordEncoder,
                           IBaseTokenUtil pBaseTokenUtil,
                           IUserDbService pUserDbService,
                           IUserWithRoleAndAuthDbService pUserWithRoleDbService,
                           IRelUserDepDbService pRelUserDepDbService) {
        super(pUserRelevantDao,pDepartmentRelevantDao, pUserConfig, pPasswordEncoder, pBaseTokenUtil);
        mUserDbService = pUserDbService;
        mUserWithRoleDbService = pUserWithRoleDbService;
        mRelUserDepDbService = pRelUserDepDbService;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public UserEntity signIn(SignInDto pSignInDto) {

        Long id = mUserDbService.findByEmail(pSignInDto.getEmail());
        if (null != id) {
            throw new ServiceException("已经存在邮箱" + pSignInDto.getEmail());
        }
        id = mUserDbService.findByPhone(pSignInDto.getPhone());
        if (null != id) {
            throw new ServiceException("已存在手机" + pSignInDto.getPhone());
        }
        UserEntity userEntity = DbDtoEntityUtil.createFromDto(pSignInDto, UserEntity.class);

        super.createUser(userEntity,null,null);
        return userEntity;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public UserEntity edit(Long pId, EditUserDto pEditUserDto) {
        UserEntity orgUserEntity = mUserDbService.check(pId);
        UserEntity newUserEntity = DbDtoEntityUtil.editByDto(orgUserEntity, pEditUserDto, UserEntity.class);
        newUserEntity = mUserDbService.updatePull(pId, newUserEntity);
        return newUserEntity;
    }

    @Override
    public UserVo info(Long pId) {
        UserEntity userEntity = mUserDbService.check(pId);
        UserVo userVo = DtoEntityUtil.trans(userEntity, UserVo.class);
        List<String> roles = getUserRoles(pId);
        userVo.setRoles(roles);
        List<RelUserAuthEntity> relUserAuthEntityList = mRelUserDepDbService.listByUserId(pId);
        userVo.setDepartments(relUserAuthEntityList);
        return userVo;
    }

    @Override
    public Page<UserVo> page(Integer pCurrent, Integer pSize, String pRoleCode, Long pDeptId, String pDeptCascade, String pUserName, String pEmail, String pPhone, String pNickName, Gender pGender, Integer pAgeMin, Integer pAgeMax) {
        Page<UserVo> pageCfg = new Page<UserVo>(pCurrent, pSize);
        if(null == pAgeMin){
            pAgeMin = -1;
        }
        if(null == pAgeMax){
            pAgeMax = -1;
        }
        if (StringUtils.hasText(pRoleCode)||null != pDeptId || StringUtils.hasText(pDeptCascade)) {
            LambdaQueryWrapper<UserWithRoleAndAuthViewEntity> queryWrapper = Wrappers.<UserWithRoleAndAuthViewEntity>lambdaQuery()
                    .eq(StringUtils.hasText(pRoleCode), UserWithRoleAndAuthViewEntity::getRoleCode, pRoleCode)
                    .eq(null != pDeptId, UserWithRoleAndAuthViewEntity::getAuthId,pDeptId)
                    .likeRight(StringUtils.hasText(pDeptCascade), UserWithRoleAndAuthViewEntity::getAuthCascade,pDeptCascade)
                    .eq(StringUtils.hasText(pUserName), UserWithRoleAndAuthViewEntity::getName, pUserName)
                    .eq(StringUtils.hasText(pEmail), UserWithRoleAndAuthViewEntity::getEmail, pEmail)
                    .eq(StringUtils.hasText(pPhone), UserWithRoleAndAuthViewEntity::getPhone, pPhone)
                    .eq(null != pGender, UserWithRoleAndAuthViewEntity::getGender, pGender)
                    .le(-1 != pAgeMin && -1 == pAgeMax, UserWithRoleAndAuthViewEntity::getBirthday, LocalDate.now().minusYears(pAgeMin))
                    .ge(-1 != pAgeMax && -1 == pAgeMin, UserWithRoleAndAuthViewEntity::getBirthday, LocalDate.now().minusYears(pAgeMax))
                    .between(-1 != pAgeMax && -1 != pAgeMin, UserWithRoleAndAuthViewEntity::getBirthday, LocalDate.now().minusYears(pAgeMin), LocalDate.now().minusYears(pAgeMax))
                    .like(StringUtils.hasText(pNickName), UserWithRoleAndAuthViewEntity::getNickName, pNickName);
            Page<UserVo> rtn = mUserWithRoleDbService.page(pageCfg, queryWrapper, UserVo.class, userEntity -> {
                UserVo userVo = DtoEntityUtil.trans(userEntity, UserVo.class);
                List<String> roles = getUserRoles(userVo.getId());
                userVo.setRoles(roles);
                List<RelUserAuthEntity> relUserAuthEntityList = mRelUserDepDbService.listByUserId(userEntity.getId());
                userVo.setDepartments(relUserAuthEntityList);
                return userVo;
            });
            return rtn;
        } else {

            LambdaQueryWrapper<UserEntity> queryWrapper = Wrappers.<UserEntity>lambdaQuery()
                    .eq(StringUtils.hasText(pUserName), UserEntity::getName, pUserName)
                    .eq(StringUtils.hasText(pEmail), UserEntity::getEmail, pEmail)
                    .eq(StringUtils.hasText(pPhone), UserEntity::getPhone, pPhone)
                    .eq(null != pGender, UserEntity::getGender, pGender)
                    .le(-1 != pAgeMin && -1 == pAgeMax, UserEntity::getBirthday, LocalDate.now().minusYears(pAgeMin))
                    .ge(-1 != pAgeMax && -1 == pAgeMin, UserEntity::getBirthday, LocalDate.now().minusYears(pAgeMax))
                    .between(-1 != pAgeMax && -1 != pAgeMin, UserEntity::getBirthday, LocalDate.now().minusYears(pAgeMin), LocalDate.now().minusYears(pAgeMax))
                    .like(StringUtils.hasText(pNickName), UserEntity::getNickName, pNickName);
            Page<UserVo> rtn = mUserDbService.page(pageCfg, queryWrapper, UserVo.class, userEntity -> {
                UserVo userVo = DtoEntityUtil.trans(userEntity, UserVo.class);
                List<String> roles = getUserRoles(userVo.getId());
                userVo.setRoles(roles);
                List<RelUserAuthEntity> relUserAuthEntityList = mRelUserDepDbService.listByUserId(userEntity.getId());
                userVo.setDepartments(relUserAuthEntityList);
                return userVo;
            });
            return rtn;
        }
    }

}
